package com.framework.workflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.framework.workflow.constant.DataDict;
import com.framework.workflow.mapper.ModuleMapper;
import com.framework.workflow.model.WfModule;
import com.framework.workflow.params.ModuleParam;
import com.framework.workflow.service.IModuleService;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.util.List;


/**
 * @author zzg
 */
@Service
public class ModuleService implements IModuleService {
    @Autowired
    private ModuleMapper baseMapper;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private WfButtonService wfButtonService;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Page<WfModule> listPage(ModuleParam param, Page<WfModule> pageParam) {
        LambdaQueryWrapper<WfModule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(param.getName()), WfModule::getName, param.getName());
        queryWrapper.like(StringUtils.isNotBlank(param.getName()), WfModule::getProcDefKey, param.getName());
        queryWrapper.orderByDesc(WfModule::getCreateTime);
        return baseMapper.selectPage(pageParam, queryWrapper);
    }

    @Override
    public String save(WfModule param) {
        boolean isAdd = StringUtils.isBlank(param.getId());
        Model model;
        if (isAdd) {
            //初始化一个空模型
            model = repositoryService.newModel();
        } else {
            model = repositoryService.getModel(param.getModuleId());
        }

        //设置一些默认信息
        int revision = 1;
        ObjectNode modelNode = objectMapper.createObjectNode();
        model.setName(param.getName());
        model.setKey(param.getProcDefKey());
        model.setMetaInfo(modelNode.toString());
        model.setVersion(revision);
        repositoryService.saveModel(model);
        String modelId = model.getId();

        //将模型id存到主表中
        param.setModuleId(modelId);

        //保存基础数据
        if (StringUtils.isNotBlank(param.getId())) {
            baseMapper.updateById(param);
        } else {
            baseMapper.insert(param);
        }

        return param.getId();
    }

    @Override
    public void deploy(String id) {
        // 根据流程定义获取模型
        Model model = repositoryService.getModel(id);
        // 设置名称
        String resourceName = model.getName()
                + DataDict.Separator.POINT.toString()
                + DataDict.Separator.BPMN_Suffix.toString();
        byte[] source = repositoryService.getModelEditorSource(model.getId());
        // 发布流程，用流发布
        Deployment deployment = repositoryService.createDeployment()
                .name(resourceName)
                .addInputStream(resourceName, new ByteArrayInputStream(source))
                .deploy();

        // 获取发布生成的流程编号
        model.setDeploymentId(deployment.getId());

        // 保存发布信息
        repositoryService.saveModel(model);

        // 获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId()).singleResult();

        String processDefinitionId = processDefinition.getId();
        repositoryService.setProcessDefinitionCategory(processDefinitionId, model.getCategory());
    }

    @Override
    public void delete(String[] ids) {
        for (String id : ids) {
            WfModule model = baseMapper.selectById(id);
            baseMapper.deleteById(model.getId());

            if (StringUtils.isNotBlank(model.getProcDefKey())) {
                // 删除按钮
                wfButtonService.delByKey(model.getProcDefKey());
                // 删除历史发布
                List<Deployment> list =repositoryService.createDeploymentQuery().processDefinitionKey(model.getProcDefKey()).list();
                list.forEach(it -> repositoryService.deleteDeployment(it.getId()));
            }

            // 删除流程定义
            if (StringUtils.isNotBlank(model.getModuleId())) {
                repositoryService.deleteModel(model.getModuleId());
            }
        }
    }

    public void updateProcDefKey(String modelId, String procDefKey) {
        QueryWrapper<WfModule> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WfModule::getModuleId, modelId);
        WfModule modules = baseMapper.selectOne(queryWrapper);
        modules.setProcDefKey(procDefKey);
        baseMapper.updateById(modules);
    }
}
